<?php

namespace Modules\Production\Repository;

use App\Services\UnitService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Modules\Production\Models\ProductionOrder;
use Modules\Production\Models\ProductionOrderDetail;
use Modules\Production\Models\ProductionProcess;
use Modules\Promanagement\Models\Processdata;
use Modules\Promanagement\Models\Processflow;
use Modules\Promanagement\Models\Provflowsional;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use App\Enums\ProductionOrderBackStatus;

class ProductionOrderRepository
{
    protected $productionOrder;

    public function __construct(ProductionOrder $productionOrder)
    {
        $this->productionOrder = $productionOrder;
    }

    /**
     * 工单修改
     * @param $postData
     */
    static public function update($id,$orderData){

        @file_put_contents('66667.txt',json_encode($orderData) . "\r\n",FILE_APPEND);

        if(!isset($orderData['FEntry']) || count($orderData['FEntry']) < 1){
            throw new \Exception('单据体【FEntry】不能为空');
        }

        try{
            DB::beginTransaction();

            $productionModel = new ProductionOrder();
            $detailModel = new ProductionOrderDetail();

            $order = $productionModel->where('fid',$id)->lockForUpdate()->first();
            if(!$order){
                throw new \Exception("内码不存在【{$id}】");
            }

            //查询全部子项
            $allItem = ProductionOrderDetailRepository::getListByProductionId($order->id)->toArray();
            $allItem = array_column($allItem,null,'fentryid');

            $backStatus = false;

            //单据体入库
            foreach ($orderData['FEntry'] as &$items){

                if(isset($allItem[$items['fentryid']])){
                    //已经存在，修改
                    $row = $allItem[$items['fentryid']];

                    if($row['fmaterialid1'] != $items['fmaterialid1']){

                        if($row['fpickedqty'] > 0){
                            throw new \Exception("子项物料【{$row['fmaterialid1']}】已领料，修改失败");
                        }

                        if(StockTaskScanRepository::getScanCountByProductionAndMaterial($order->id,$row['fmaterialid1']) > 0){
                            throw new \Exception("子项物料【{$row['fmaterialid1']}】修改失败，已扫描备料请先释放库存");
                        }

                    }

                    if($items['fpickedqty'] < $row['fpickedqty']){
                        throw new \Exception("子项物料【{$row['fmaterialid1']}】已领数量不能小于WMS已领数量");
                    }

                    $updateData = [
                        'fseq'              => $items['fseq'],
                        'fmaterialid1'      => $items['fmaterialid1'],
                        'fmaterialname1'    => $items['fmaterialname1'],
                        'fmaterialmodel1'   => $items['fmaterialmodel1'],
                        'fmodel1'           => $items['fmodel1'],
                        'fpositionno'       => $items['fpositionno'],
                        'ffixscrapqty'      => $items['ffixscrapqty'],
                        'fscraprate'        => $items['fscraprate'],
                        'fsupplymode'       => $items['fsupplymode'],
                        //'fproxyissuetype'   => $items['fproxyissuetype'],
                        //'fmemo1'            => $items['fmemo1'],
                        'fmustqty'          => $items['fmustqty'],
                        'fpickedqty'        => $items['fpickedqty'],
                        'fnumerator'        => $items['fnumerator'],
                        'fdenominator'      => $items['fdenominator'],
                        'fuserate'          => $items['fuserate'],
                        'funitid1_number'   => $items['funitid1_number'],
                        'funitid1_name'     => $items['funitid1_name'],
                    ];

                    //应发数量有变，将已备货状态改为备货中
                    if($items['fmustqty'] != $row['fmustqty'] && $row['back_status'] == 2){
                        $updateData['back_status'] = 1;
                        $backStatus = true;
                    }

                    $detailModel->where('id',$row['id'])->update($updateData);

                    //删除已处理子项
                    unset($allItem[$items['fentryid']]);

                }else{
                    //不存在，新增
                    $items['production_order_id'] = $order->id;
                    $items['fmaterialmodel1'] = $items['fmaterialmodel1'] == null ? '' : $items['fmaterialmodel1'];
                    $items['fmodel1'] = $items['fmodel1'] == null ? '' : $items['fmodel1'];
                    $items['fpositionno'] = $items['fpositionno'] == null ? '' : $items['fpositionno'];
                    $items['fmemo1'] = $items['fmemo1'] == null ? '' : $items['fmemo1'];
                    $items['fownerid_number'] = $items['fownerid_number'] == null ? '' : $items['fownerid_number'];
                    $items['fownerid_name'] = $items['fownerid_name'] == null ? '' : $items['fownerid_name'];
                    //ProductionOrderDetail::insert($items);
                    (new ProductionOrderDetail())->storeBy($items);
                }
            }

            if(!empty($allItem)){
                //删除不存在子项

                foreach ($allItem as $val){
                    if($val['fpickedqty'] > 0){
                        throw new \Exception("子项物料【{$val['fmaterialid1']}】已领料，删除失败");
                    }

                    if(StockTaskScanRepository::getScanCountByProductionAndMaterial($order->id,$val['fmaterialid1']) > 0){
                        throw new \Exception("子项物料【{$val['fmaterialid1']}】修改失败，已扫描备料请先释放库存");
                    }

                    $detailModel->where('id',$val['id'])->delete();
                }

            }

            //生产工单头修改
            if($backStatus && $order->back_status == ProductionOrderBackStatus::ALREADY_BACK->value){
                $orderData['back_status'] = ProductionOrderBackStatus::PART_BACK->value;
            }
            $productionModel->updateBy($order->id,$orderData);

            Db::commit();
            return [];

        }catch (\Exception $e){
            @file_put_contents('66667.txt',$e->getMessage() . "\r\n",FILE_APPEND);
            Db::rollBack();
            throw $e;
        }
    }

    /**
     * 根据id获取一条生产订单信息
     * @param $id
     * @return mixed
     */
    static public function getOrderById($id){
        return ProductionOrder::find($id);
    }

    /**
     * 生产订单设为已分配
     * @param $orderId
     * @return mixed
     */
    static public function setOrderStockUser($orderId){
        return ProductionOrder::whereIn('id',$orderId)->update(['stock_who' => 1]);
    }

    /**
     * 根据生产工单号查询信息
     * @param $docno
     */
    static public function getIdByDocno($docno){
        return ProductionOrder::where('fbillno',$docno)->first();
    }

    /**
     * 工艺流程绑定
     * @param $postData
     */
    static public function bindFlow($postData){

        if(!isset($postData['ids']) || count($postData['ids']) < 1){
            throw new \Exception('ids参数不能为空');
        }

        if(!isset($postData['flow_code']) || empty($postData['flow_code'])){
            throw new \Exception('flow_code参数不能为空');
        }

        //工序流程
        $flowInfo = Processflow::where('pflcode',$postData['flow_code'])->first();
        if(!$flowInfo){
            throw new \Exception("工艺流程代码：{$postData['flow_code']}不存在");
        }

        //所属工艺
        //provflowsional
        $process = Provflowsional::where('processflow_id',$flowInfo->id)->with('processdata')->orderBy('process','asc')->get();
        /*$process = Processdata::whereIn('id',$flowInfo->purchaseorder_id)->get();*/
        if($process->isEmpty()){
            throw new \Exception("工艺流程代码[{$postData['flow_code']}]绑定的工艺资料为空");
        }

        try {

            DB::beginTransaction();

            foreach ($postData['ids'] as $productionId){

                $production = ProductionOrderRepository::getOrderById($productionId);
                //跳过相同工艺流程的工单
                if($production->flow_code == $flowInfo->pflcode){
                    continue;
                }

                //查询是否已经工序汇报
                if(ProcessRepository::hasProcessReport($productionId)){
                    throw new \Exception("工单【{$production->fbillno}】工序报工已汇报，不允许修改工艺流程");
                }

                ProductionProcess::where('production_order_id',$productionId)->delete();

                $parentId = 0;
                foreach($process as $key => $val){
                    $productionProcessItem = [
                        'production_order_id'   => $productionId,
                        'sort'                  => $val->process,
                        'process_code'          => $val->processdata->workingcode,
                        'process_name'          => $val->processdata->processname,
                        'parent_id'             => $parentId,
                    ];
                    $parentId = (new ProductionProcess())->storeBy($productionProcessItem);
                }
            }

            ProductionOrder::whereIn('id',$postData['ids'])->update([
                'flow_code' => $flowInfo->pflcode,
                'flow_name' => $flowInfo->processname
            ]);

            DB::commit();

        }catch (\Exception $e){
            DB::rollBack();
            throw $e;
        }

    }

    /**
     * 生成生产工单二维码
     * @param $productionNo
     */
    static public function makeProductionQrCode($productionNo){

        $fileName = "{$productionNo}.png";
        $dir = 'production/';
        $exends = public_path() . $dir . $fileName;
        if(file_exists($exends)){
            return env('APP_URL') . '/' . $dir . $fileName;
        }
        $qrImg = QrCode::format('png')->size(400)->generate($productionNo);
        Storage::disk('production')->put($fileName,$qrImg);
        return env('APP_URL') . '/' . $dir . $fileName;
    }

    /**
     * 生成生产工单工序二维码
     * @param $productionNo
     */
    static public function makeFlowQrCode($productionNo,$processId){

        $fileName = "{$productionNo}@{$processId}.png";
        $dir = 'production/';
        $exends = public_path() . $dir . $fileName;
        if(file_exists($exends)){
            return env('APP_URL') . '/' . $dir . $fileName;
        }
        $qrImg = QrCode::format('png')->size(400)->generate("{$productionNo}@$processId");
        Storage::disk('production')->put($fileName,$qrImg);
        return env('APP_URL') . '/' . $dir . $fileName;
    }

    /**
     * 检查工单备货状态（子项全部备货完成将工单设为已备货）
     * @param $productionId
     */
    static public function checkStockStatus($productionId){
        $waitBackCount = ProductionOrderDetail::where('production_order_id',$productionId)->whereIn('back_status',[0,1])->count();
        if($waitBackCount == 0){
            self::updateById($productionId,['back_status' => 2]);
        }else{
            self::updateById($productionId,['back_status' => 1]);
        }
    }

    /**
     * 按生产工单id修改单据头数据
     * @param $id
     * @param $data
     * @return mixed
     */
    static public function updateById($id,$data){
        return ProductionOrder::where('id',$id)->update($data);
    }

    /**
     * 自增某个字段
     * @param $productionId
     * @param $field
     * @param $number
     */
    static public function increment($productionId,$field,$number){
        return ProductionOrder::where('id',$productionId)->increment($field,$number);
    }

    /**
     * 工单列表
     * @param $params
     * @return mixed
     */
    static public function getOrderList($params){
        $builder = self::getWhere($params);

        $limit = isset($params['limit']) ? $params['limit'] : 100;

        return $builder->with('stockUser')->paginate($limit)->toArray();

    }

    /**
     * 工单列表过滤条件
     * @param $params
     * @return ProductionOrder
     */
    static public function getWhere($params){

        $builder = new ProductionOrder();

        if(isset($params['start_date']) && $params['start_date'] != '' && isset($params['end_date']) && $params['end_date'] != ''){
            $start = strtotime($params['start_date']);
            $end = strtotime('+ 1 day',strtotime($params['end_date']));
            $builder = $builder->whereBetween('created_at',[$start,$end]);
        }

        //组织代码筛选
        if(isset($params['fprdorgid_number']) && $params['fprdorgid_number'] != ''){
            $builder = $builder->where('fprdorgid_number',$params['fprdorgid_number']);
        }

        //车间代码筛选
        if(isset($params['fworkshopid_number']) && $params['fworkshopid_number'] != ''){
            $builder = $builder->where('fworkshopid_number',$params['fworkshopid_number']);
        }

        return $builder;
    }
}
